<template>
  <div class="">结果见控制台</div>
</template>

<script setup lang="ts">
  // #region  普通常用类型
  // 布尔、数字、字符串、数组（类型数组、数组泛型形式）、any
  let bool: boolean = true // boolean 类型
  let num: number = 1 // number 类型
  let str: string = 'hellow word' // string 类型
  let numArr: number[] = [1, 2, 3] // number数组 类型
  let arrNum: Array<number> = [1, 2, 3] // 数组泛型形式：number数组类型
  let unknow: any = true // any类型，即任一类型
  unknow = 'maybe a string instead'
  unknow = false
  console.log(bool, num, str, numArr, arrNum, unknow)

  // 元组
  let tupleData: [number, string, boolean] = [1, '2', false]
  console.log(tupleData)
  // #endregion

  // #region enum枚举
  enum PositionTypes {
    TOP,
    RIGHT,
    BOTTOM,
    LEFT
  }
  // 用值，则会得到 属性名的字符串
  const top1 = PositionTypes[0] // TOP
  // 用指定属性，则会得到 值
  const top2 = PositionTypes.TOP // 0
  console.log(top1, top2, PositionTypes)

  // enum 数字枚举 设置第一个属性的值，后续就会自动递增
  enum PositionTypesNum {
    TOP = 2,
    RIGHT,
    BOTTOM,
    LEFT
  }
  const topNum1 = PositionTypesNum[2] // TOP
  const topNum2 = PositionTypesNum.TOP // 2
  console.log(topNum1, topNum2, PositionTypesNum)

  // enum 数字枚举 赋值重复的时候，调用会返回最后一个
  enum PositionTypesNum1 {
    TOP = 2,
    RIGHT = 2,
    BOTTOM,
    LEFT
  }
  const topNum11 = PositionTypesNum1[2] // RIGHT
  const topNum22 = PositionTypesNum1.TOP // 2
  console.log(topNum11, topNum22, PositionTypesNum1)

  // enum 字符串枚举 每一个属性都需要初始化值，否则会报错
  enum PositionTypesStr {
    TOP = 'top',
    RIGHT = 'right',
    BOTTOM = 'bottom',
    LEFT = 'left'
  }
  // 字符串枚举，就只能用属性名取值了
  const topStr = PositionTypesStr.TOP // 'top'
  console.log(topStr, PositionTypesStr)

  // enum 字符串枚举 当等号左侧和右侧重复的时候，左侧优先
  enum demoTypesStr1 {
    a = 'b',
    b = 'a',
    c = 'a'
  }
  const demo11 = demoTypesStr1['a'] // 'b'
  const demo12 = demoTypesStr1.a // 'b'
  console.log(demo11, demo12, demoTypesStr1)

  // enum 字符串枚举 当等号左侧和右侧重复的时候，左侧优先
  enum demoTypesStr2 {
    a = 'a',
    b = '1',
    c = 'c'
  }
  const demo21 = demoTypesStr2[1] // 'b'
  const demo22 = demoTypesStr2.a // 'b'
  console.log(demo21, demo22, demoTypesStr2)

  //  当枚举值不是数字的时候，下一个必须设置枚举值
  enum demoTypesAny3 {
    a, // a=0
    b = 3, // b=3
    c, // c=4
    e = 'q1', // e="q1"
    f = 5 // f=5，此处不能直接写f
  }
  console.log(demoTypesAny3)

  //  用 const 修饰符来声明枚举，编译后的js代码将不会出现额外的声明代码
  enum PositionTypesSecond {
    UP,
    DOWN,
    LEFT,
    RIGHT
  }
  const enum PositionTypesSeconds {
    SPRING = 'SPRING',
    SUMMER = 'SUMMER',
    AUTUMN = 'AUTUMN',
    WINTER = 'WINTER'
  } // 编译后看不到
  const up = PositionTypesSecond.UP // 0
  const spring = PositionTypesSeconds.SPRING // 'SPRING'
  console.log(PositionTypesSecond, up, spring)
  // #endregion

  // #region any和unknown
  // any : 任意类型
  // unknown : 未知的类型
  // 任何类型都能分配给 unknown ，但 unknown 不能分配给其他基本类型，而 any 啥都能分配和被分配
  // any demo
  let testAny: any
  testAny = true // ok
  testAny = 123 // ok
  testAny.toFixed(2) // ok
  let testAny1: string = testAny // ok
  console.log(testAny1) // 123
  //  unkonwn demo
  let testUnknown: unknown
  testUnknown = true // ok
  testUnknown = 123 //ok
  //  testUnknown.toFixed(2) // error
  //  let testUnknown1: string = testUnknown // error
  console.log(testUnknown)

  // 少用any，未知类型可用unknown
  function getLength(value: unknown): number {
    if (typeof value === 'string') {
      // 因为类型保护的原因，此处 value 被判断为 string 类型
      return value.length
    }

    return 0
  }
  console.log(getLength('aabbccdd')) // 8
  console.log(getLength(0.001)) // 0
  // #endregion

  // #region never
  // never 用户控制流分析
  //   function neverReach(): never {
  //     throw new Error('an error')
  //   }

  //   const x = neverReach()
  //   x.toFixed(2) // Property 'toFixed' does not exist on type 'never'.

  // never 还可以用于联合类型的幺元
  type T0 = string | number | never // => type T0 = string | number
  let a: T0
  a = 1
  console.log(a)
  // #endregion
</script>

<style lang="less" scoped></style>
